home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 23
/
Aminet 23 (1998)(GTI - Schatztruhe)[!][Feb 1998].iso
/
Aminet
/
misc
/
emu
/
DCMtoImg.lha
/
dcmtoatr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-30
|
10KB
|
431 lines
/*
** dcmtoatr.c -- written by Chad Wagner
**
** Revision History:
** 31 May 95 cmwagner@gate.net
** 1 Jun 95 cmwagner@gate.net
** added in some portability macros from dcm.c
** added in read_atari16() function from dcm.c
** wrote write_atari16() function
** did a general clean-up of the code
** 1 Jun 95 crow@cs.dartmouth.edu
** did a clean-up of the code, hopefully resolving any
** portability issues
** 2 Jun 95 cmwagner@gate.net and crow@cs.dartmouth.edu
** Allow for multi-file DCM files, after they've been
** combined into a single file
** 5 Jun 95 cmwagner@gate.net
** Fixed decoding routines to handle double density diskettes
** 30 Oct 97 willik@bellatlantic.net
** Added lines to allow compilation with DICE under AmigaDOS
*/
/* Include files */
#include <stdio.h>
#include <string.h>
/* prototypes */
void decode_C1(void);
void decode_C3(void);
void decode_C4(void);
void decode_C6(void);
void decode_C7(void);
void decode_FA_atr(void);
int read_atari16(FILE *);
void write_atari16(FILE *,int);
int read_offset(FILE *);
void read_sector(FILE *);
void write_sector(FILE *);
/*
** Portability macros
** 1 Jun 95 crow@cs.dartmouth.edu (Preston Crow)
*/
#if defined(__MSDOS) || defined(__MSDOS__) || defined(_MSDOS) || defined(_MSDOS_)
#define MSDOS /* icky, icky, icky! */
#endif
#ifndef SEEK_SET
#define SEEK_SET 0 /* May be missing from stdio.h */
#endif
/* version of this program, as seen in usage message */
#define VERSION "1.2"
/* this is used to calculate seek offsets */
#ifndef _DCC
#define SOFFSET ((((long)cursec - 1) * (cursec < 4 ? 128 : secsize)) + \
16 - (cursec > 3 ? 384 : 0))
#else
#define SOFFSET ((((long)cursec - 1) * (cursec < 4 ? 128 : secsize)) + 16)
#endif
/* Global variables */
FILE *fin,*fout;
unsigned int secsize;
unsigned short cursec=0,maxsec=0;
unsigned char createdisk=0,working=0,last=0,density,buf[256];
int doprint=1; /* True for diagnostic output */
/*
** main()
*/
int main(int argc,char **argv)
{
unsigned char archivetype; /* Block type for first block */
unsigned char blocktype; /* Current block type */
unsigned char tmp; /* Temporary for read without clobber on eof */
unsigned char imgin[256],imgout[256]; /* file names */
unsigned char done=0; /* completion flag */
char *self; /* program name from argv[0] */
#ifdef MSDOS
if ((self = strrchr(argv[0],'\\')) == NULL)
#else
if ((self = strrchr(argv[0],'/')) == NULL)
#endif
{
self = argv[0];
}
else
self++; /* Skip the slash */
--argc;++argv; /* Don't look at the filename anymore */
/* Process switches */
if (argc) while (*argv[0]=='-') {
int nomore=0;
++argv[0]; /* skip the '-' */
while(*argv[0]) {
switch(*argv[0]) {
case '-':
nomore=1;
break;
case 'q':
case 'Q':
doprint = !doprint;
break;
default:
fprintf(stderr,"Unsupported switch: %c\n",*argv[0]);
fprintf(stderr,"%s "VERSION" by cmwagner@gate.net\n",self);
fprintf(stderr,"%s [-q] input[.dcm] [output[.atr]]\n",self);
exit(1);
}
++argv[0]; /* We've processed this flag */
}
--argc;++argv; /* Done processing these flags */
if(nomore) break; /* Filename may begin with '-' */
}
if (argc<1 || argc>2) {
fprintf(stderr,"%s "VERSION" by cmwagner@gate.net\n",self);
fprintf(stderr,"%s [-q] input[.dcm] [output[.atr]]\n",self);
exit(1);
}
strcpy(imgin,argv[0]);
if (strrchr(imgin,'.') == NULL)
strcat(imgin,".dcm");
if (argc==2)
strcpy(imgout,argv[1]);
else {
char *p;
strcpy(imgout,imgin);
if ((p = strrchr(imgout,'.')) != NULL)
*p = 0;
}
if (strrchr(imgout,'.') == NULL)
strcat(imgout,".atr");
if ((fin = fopen(imgin,"rb")) == NULL) {
fprintf(stderr,"I couldn't open \"%s\" for reading.\n",imgin);
exit(1);
}
archivetype = blocktype = fgetc(fin);
switch(blocktype) {
case 0xF9:
case 0xFA:
break;
default:
fprintf(stderr,"0x%02X is not a known header block.\n",blocktype);
exit(1);
}
if ((fout = fopen(imgout,"rb")) != NULL) {
fprintf(stderr,"I can't use \"%s\" for output, it already exists.\n",imgout);
exit(1);
} else {
fout = fopen(imgout,"wb");
}
rewind(fin);
do {
if(doprint) printf("\rCurrent sector: %4u",cursec);
#ifdef MSDOS
if (kbhit()) {
if (getch() == 27) {
fprintf(stderr," Processing terminated by user.\n");
exit(1);
}
}
#endif
if (feof(fin)) {
fflush(stdout); /* Possible buffered I/O confusion fix */
if ((!last) && (blocktype == 0x45) && (archivetype == 0xF9)) {
fprintf(stderr,"\nMulti-part archive error.\n");
fprintf(stderr,"To process these files, you must first combine the files into a single file.\n");
#ifdef MSDOS
fprintf(stderr,"\tCOPY /B file1.dcm+file2.dcm+file3.dcm newfile.dcm\n");
#else
fprintf(stderr,"\tcat file1.dcm file2.dcm file3.dcm > newfile.dcm\n");
#endif
}
else {
fprintf(stderr," EOF before end block.\n");
}
exit(1);
}
/*
if (working) {
if (((((long)cursec - 1) * secsize) + 16) != ftell(fout)) {
fprintf(stderr," Output has desynched.\nfin=%lu fout=%lu != %lu "
"cursec=%u secsize=%u\n",ftell(fin),ftell(fout),
(((long)cursec - 1) * secsize) + 16,cursec,secsize);
exit(1);
}
}
*/
tmp = fgetc(fin); /* blocktype is needed on EOF error--don't corrupt it */
if (feof(fin)) continue; /* Will abort on the check at the top of the loop */
blocktype = tmp;
switch(blocktype) {
case 0xF9:
case 0xFA:
/* New block */
decode_FA_atr();
break;
case 0x45:
/* End block */
working=0;
if (last) {
if (doprint) printf("\r%s has been successfully decompressed.\n",imgout);
fclose(fin);
fclose(fout);
done=1; /* Normal exit */
}
break;
case 0x41:
case 0xC1:
decode_C1();
break;
case 0x43:
case 0xC3:
decode_C3();
break;
case 0x44:
case 0xC4:
decode_C4();
break;
case 0x46:
case 0xC6:
decode_C6();
break;
case 0x47:
case 0xC7:
decode_C7();
break;
default:
fprintf(stderr,"\n\n0x%02X is not a known block type. File may be "
"corrupt.\n",blocktype);
exit(1);
} /* end case */
if ((blocktype != 0x45) && (blocktype != 0xFA) &&
(blocktype != 0xF9)) {
if (!(blocktype & 0x80)) {
cursec=read_atari16(fin);
fseek(fout,SOFFSET,SEEK_SET);
} else {
cursec++;
}
}
} while(!done); /* end do */
return(0); /* Should never be executed */
}
void decode_C1(void)
{
int secoff,tmpoff,c;
tmpoff=read_offset(fin);
c=fgetc(fin);
for (secoff=0; secoff<secsize; secoff++) {
buf[secoff]=c;
}
c=tmpoff;
for (secoff=0; secoff<tmpoff; secoff++) {
c--;
buf[c]=fgetc(fin);
}
write_sector(fout);
}
void decode_C3(void)
{
int secoff,tmpoff,c;
secoff=0;
do {
if (secoff)
tmpoff=read_offset(fin);
else
tmpoff=fgetc(fin);
for (; secoff<tmpoff; secoff++) {
buf[secoff]=fgetc(fin);
}
if (secoff == secsize)
break;
tmpoff=read_offset(fin);
c=fgetc(fin);
for (; secoff<tmpoff; secoff++) {
buf[secoff] = c;
}
} while(secoff < secsize);
write_sector(fout);
}
void decode_C4(void)
{
int secoff,tmpoff;
tmpoff=read_offset(fin);
for (secoff=tmpoff; secoff<secsize; secoff++) {
buf[secoff]=fgetc(fin);
}
write_sector(fout);
}
void decode_C6(void)
{
write_sector(fout);
}
void decode_C7(void)
{
read_sector(fin);
write_sector(fout);
}
void decode_FA_atr(void)
{
unsigned char c;
if (working) {
fprintf(stderr,"\nTrying to start section but last section never had "
"an end section block.\n");
exit(1);
}
c=fgetc(fin);
density=((c & 0x70) >> 4);
last=((c & 0x80) >> 7);
switch(density) {
case 0:
maxsec=720;
secsize=128;
break;
case 2:
maxsec=720;
secsize=256;
break;
case 4:
maxsec=1040;
secsize=128;
break;
default:
fprintf(stderr," Density type is unknown, density type=%u\n",density);
exit(1);
}
if (createdisk == 0) {
createdisk = 1;
/* write out atr header */
/* special code, 0x0296 */
write_atari16(fout,0x296);
/* image size (low) */
#ifndef _DCC
write_atari16(fout,(short)(((long)maxsec * secsize) >> 4));
#else
write_atari16(fout,maxsec);
#endif
/* sector size */
write_atari16(fout,secsize);
/* image size (high) */
#ifndef _DCC
write_atari16(fout,(short)(((long)maxsec * secsize) >> 20));
#else
write_atari16(fout,0);
#endif
/* 8 bytes unused */
write_atari16(fout,0);
write_atari16(fout,0);
write_atari16(fout,0);
write_atari16(fout,0);
memset(buf,0,256);
for (cursec=0; cursec<maxsec; cursec++) {
fwrite(buf,secsize,1,fout);
}
}
cursec=read_atari16(fin);
fseek(fout,SOFFSET,SEEK_SET);
working=1;
}
/*
** read_atari16()
** Read a 16-bit integer with Atari byte-ordering.
** 1 Jun 95 crow@cs.dartmouth.edu (Preston Crow)
*/
int read_atari16(FILE *fin)
{
int ch_low,ch_high; /* fgetc() is type int, not char */
ch_low = fgetc(fin);
ch_high = fgetc(fin);
return(ch_low + 256*ch_high);
}
void write_atari16(FILE *fout,int n)
{
unsigned char ch_low,ch_high;
ch_low = (unsigned char)(n&0xff);
ch_high = (unsigned char)(n/256);
fputc(ch_low,fout);
fputc(ch_high,fout);
}
int read_offset(FILE *fin)
{
int ch; /* fgetc() is type int, not char */
ch = fgetc(fin);
if (ch == 0)
ch = 256;
return(ch);
}
void read_sector(FILE *fin)
{
fread(buf,(cursec < 4 ? 128 : secsize),1,fin);
}
void write_sector(FILE *fout)
{
fwrite(buf,(cursec < 4 ? 128 : secsize),1,fout);
}